package cn.middle.edge.portal;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.UUID;

import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import javax.validation.constraints.NotNull;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.util.ResourceUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.multipart.commons.CommonsMultipartResolver;

import com.middle.common.basic.enums.Status;
import com.middle.common.result.ApiResponse;
import com.middle.common.result.Page;

import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.middle.edge.dto.EdgeDto;
import cn.middle.edge.dto.EdgeServiceDto;
import cn.middle.edge.entity.EdgePark;
import cn.middle.edge.entity.Server;
import cn.middle.edge.service.EdgeParkService;
import cn.middle.edge.service.ServerService;
import cn.middle.remote.edge.EdgeClient;

/**
 * 边缘服务信息
 * @author KING
 *
 */
@Controller
@RequestMapping("/server")
public class ServerController {

	private final Logger logger = LoggerFactory.getLogger(this.getClass());
	
	private final static String PREFIX = "edge/server/";
	
	
	private final static String PLUGIN_PATH = File.separator + "static" + File.separator + "upload" + File.separator + "plugin";
	
	@Autowired
	private ServerService serverService;
	
	@Autowired
	private EdgeParkService edgePackService;
	
	@Autowired
	private EdgeClient client;
	
	/**
	 * 服务列表
	 * @param pageNum 页码
	 * @param limit  每页数
	 * @param serviceId  服务ID
	 * @param serviceName  服务名称
	 * @param status  服务状态
	 * @param modelMap
	 * @return
	 */
	@SaCheckPermission("server:list")
	@GetMapping("/list")
	public String list(@RequestParam(value = "pageNum", defaultValue = "1") Integer pageNum,
			@RequestParam(value = "limit", defaultValue = "10") Integer limit, String serviceId, String serviceName,
			 Byte status, ModelMap modelMap) {
		Page<Server> servers = serverService.listConditions(pageNum, limit, serviceId, serviceName, status);
		modelMap.put("serviceId", serviceId);
		modelMap.put("serviceName", serviceName);
		modelMap.put("status", status);
		modelMap.put("pageInfo", servers);
		return PREFIX + "list";
	}
	
	@SaCheckPermission("server:add")
	@GetMapping("/add")
	public String add() {
		return PREFIX + "add";
	}
	
	@SaCheckPermission("server:add")
	@SuppressWarnings("unchecked")
	@ResponseBody
	@PostMapping("/add")
	public ApiResponse<Boolean> add(@Valid Server server,ModelMap modelMap){
		logger.info("serverInfo {}", server);
		if(!serverService.validateServerCode(server.getServerCode())) {
			return ApiResponse.FailCustomWithMessage(String.valueOf(-1000), "服务编码已被占用");
		}
		server.setStatus(Status.DLE.code());
		server.setUpdateTime(new Date());
		serverService.save(server);
		return ApiResponse.successWithData(true);
	}
	
	@SaCheckPermission("server:edit")
	@GetMapping("/edit")
	public String edit(@NotNull(message = "id不能为空")Long id,ModelMap modelMap) {
		modelMap.put("model",serverService.getById(id));
		return PREFIX + "edit";
	}
	
	@SaCheckPermission("server:delete")
	@SuppressWarnings("unchecked")
	@ResponseBody
	@GetMapping("/delete")
	public ApiResponse<Boolean> delete(Long id) {
		if(id == null) {
			return ApiResponse.FAIL_WITH_PARAME_MISSING;
		}
		Server sysServer = serverService.getById(id);
		if(sysServer == null) {
			return ApiResponse.FailCustomWithMessage(String.valueOf(-1000), "该服务信息不存在，请您注意检查！");
		}
		serverService.deleteById(id);
		return ApiResponse.successWithData(true);
	}
	
	@SaCheckPermission("server:edit")
	@SuppressWarnings("unchecked")
	@ResponseBody
	@PostMapping("/edit")
	public ApiResponse<Boolean> edit(@Valid Server server,ModelMap modelMap){
		logger.info("serverInfo {}", server);
		if(server.getId() == null) {
			return ApiResponse.FAIL_WITH_PARAME_MISSING;
		}
		Server sysServer = serverService.getById(server.getId());
		if(sysServer == null) {
			return ApiResponse.FailCustomWithMessage(String.valueOf(-1000), "该服务信息不存在，请您注意检查！");
		}
		if(!sysServer.getServerCode().equals(server.getServerCode()) && !serverService.validateServerCode(server.getServerCode())) {
			return ApiResponse.FailCustomWithMessage(String.valueOf(-1000), "服务编码已被占用");
		}
		server.setUpdateTime(new Date());
		serverService.update(server);
		return ApiResponse.successWithData(true);
	}
	
	/**
	 * 同步边缘服务信息到云端(实现逻辑待定)
	 * @return
	 */
	@SaCheckPermission("server:cound")
	@SuppressWarnings("unchecked")
	@ResponseBody
	@GetMapping("/uploadCound")
	public ApiResponse<Boolean> uploadCound(Byte uploadType,Long id){
		EdgePark park = this.edgePackService.theOne();
		if(park == null) {
			return ApiResponse.FailCustomWithMessage(String.valueOf(-1000), "园区信息获取为空！");
		}
		
		EdgeDto dto = to(park);
		List<EdgeServiceDto> serviceDtos = new ArrayList<>();
		dto.setServices(serviceDtos);
		if(uploadType == 0) { //全局同步
			List<Server> list = serverService.getAll();
			for(Server server : list) {
				serviceDtos.add(to(server));
			}
			
		}else { //根据ID同步
			if(id == null) {
				return ApiResponse.FAIL_WITH_PARAME_MISSING;
			}
			
			Server server = this.serverService.getById(id);
			if(server != null) {
				serviceDtos.add(to(server));
			}
		}
		
		this.client.registration(UUID.randomUUID().toString(), dto);
		return ApiResponse.successWithData(true);
	}
	
	private EdgeDto to(EdgePark park) {
		EdgeDto dto = new EdgeDto();
		dto.setAddress(park.getAddress());
		dto.setDescribe(park.getDescription());
		dto.setEdgeId(park.getCode());
		dto.setEdgeName(park.getName());
		dto.setRegistryTime(new Date());
		dto.setClientId(1); //客户端ID
		return dto;
	}
	
	@ResponseBody
	@SuppressWarnings("rawtypes")
	@SaCheckPermission("server:status")
	@GetMapping("/status/{id}")
	public ApiResponse status(@PathVariable("id")Long id) {
		Server server = serverService.getById(id);
	    if(server == null) {
	    	return ApiResponse.FailCustomWithMessage(String.valueOf(-1000), "服务信息不存在！");
	    }
	    server.setStatus(Status.find(server.getStatus()) == Status.Active ?  Status.DLE.code() : Status.Active.code() );
	    this.serverService.update(server);
	    //TODO 获取最新状态，停启用插件
	   // Status newStatus =  Status.find(server.getStatus());
	    return ApiResponse.SUCCESS;
	}
	
	@SaCheckPermission("server:plugin")
	@GetMapping("/plugin/{id}")
	public String uploadPlugin(@PathVariable("id")Long id) {
		return PREFIX + "plugin";
	}
	
	
	//https://www.cnblogs.com/exmyth/p/14421264.html
	@SaCheckPermission("server:plugin")
	@ResponseBody
	@PostMapping("/plugin")
	@SuppressWarnings("rawtypes")
	public ApiResponse uploadPlugin(HttpServletRequest request,@RequestParam(value = "id",required = true) Long id) {
		CommonsMultipartResolver commonsMultipartResolver = new CommonsMultipartResolver(request.getSession().getServletContext());
		if(commonsMultipartResolver.isMultipart(request)) {
			Server server = serverService.getById(id);
		    if(server == null) {
		    	return ApiResponse.FailCustomWithMessage(String.valueOf(-1000), "服务信息不存在！");
		    }
			MultipartHttpServletRequest multipartHttpServletRequest = (MultipartHttpServletRequest)request;
			List<MultipartFile> list = multipartHttpServletRequest.getFiles("uploadfile");
			for(MultipartFile multipartFile:list){
				String fileName = multipartFile.getOriginalFilename();//文件真名
				String substring = fileName.substring(fileName.lastIndexOf("."));//后缀
				String upName = UUID.randomUUID().toString()+substring;//修改后的
				try{
					String filePath = ResourceUtils.getURL("classpath:").getPath() + PLUGIN_PATH;
					File path = new File(filePath);
					if(path.exists()){
						if(StringUtils.hasText(server.getPluginPath())) {
							//TODO应该要先移除jar插件的，销毁在JVM中的创建的类，当前选移除Jar
							File oldJar = new File(server.getPluginPath());
							if(oldJar.isFile()) {
								oldJar.delete();//删除旧有的插件Jar
							}
						}
					}else {
						path.mkdirs();  //创建目录
					}
					String fileJarPath = path.getAbsolutePath() + File.separator + upName;
					multipartFile.transferTo(new File(fileJarPath));
					//更新插件路径
					server.setPluginPath(fileJarPath);
					serverService.update(server);
				} catch (IOException e){
					logger.error(e.getMessage(),e);
					return ApiResponse.UNKNOWN_ERROR;
				}
			}
		}else {
			return ApiResponse.FailCustomWithMessage(String.valueOf(-1000), "上传文件不存在！");
		}
		return ApiResponse.SUCCESS;
	}
	
	private EdgeServiceDto to(Server server) {
		EdgeServiceDto dto = new EdgeServiceDto();
		dto.setServiceId(server.getServerCode());
		dto.setServiceName(server.getServerName());
		dto.setServiceType(server.getServerType());
		dto.setStatus(server.getStatus());
		return dto;
	}
	
}
